package com.zenithmind.user.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.zenithmind.common.annotation.DataCache;
import com.zenithmind.common.cache.DataCacheEvict;
import com.zenithmind.user.mapper.TenantConfigMapper;
import com.zenithmind.user.pojo.domain.TenantConfig;
import com.zenithmind.user.service.TenantConfigService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 租户配置服务实现类
 * 
 * @author ZenithMind
 * @since 2024-06-30
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class TenantConfigServiceImpl extends ServiceImpl<TenantConfigMapper, TenantConfig> implements TenantConfigService {

    private final ObjectMapper objectMapper;

    @Override
    @DataCache(prefix = "tenant:config", key = "#tenantId + ':' + #configKey", expireTime = 3600)
    public String getConfigValue(String tenantId, String configKey) {
        if (!StringUtils.hasText(tenantId) || !StringUtils.hasText(configKey)) {
            return null;
        }

        TenantConfig config = baseMapper.selectByTenantIdAndKey(tenantId, configKey);
        return config != null ? config.getConfigValue() : null;
    }

    @Override
    public String getConfigValue(String tenantId, String configKey, String defaultValue) {
        String value = getConfigValue(tenantId, configKey);
        return StringUtils.hasText(value) ? value : defaultValue;
    }

    @Override
    public <T> T getConfigValue(String tenantId, String configKey, Class<T> clazz) {
        return getConfigValue(tenantId, configKey, clazz, null);
    }

    @Override
    public <T> T getConfigValue(String tenantId, String configKey, Class<T> clazz, T defaultValue) {
        String value = getConfigValue(tenantId, configKey);
        if (!StringUtils.hasText(value)) {
            return defaultValue;
        }

        try {
            if (clazz == String.class) {
                return clazz.cast(value);
            } else if (clazz == Integer.class) {
                return clazz.cast(Integer.valueOf(value));
            } else if (clazz == Long.class) {
                return clazz.cast(Long.valueOf(value));
            } else if (clazz == Double.class) {
                return clazz.cast(Double.valueOf(value));
            } else if (clazz == Boolean.class) {
                return clazz.cast(Boolean.valueOf(value));
            } else {
                // 对于复杂对象，使用JSON反序列化
                return objectMapper.readValue(value, clazz);
            }
        } catch (Exception e) {
            log.error("配置值类型转换失败: {} -> {}", value, clazz.getSimpleName(), e);
            return defaultValue;
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @DataCacheEvict(prefix = "tenant:config", key = "#tenantId + ':' + #configKey")
    public boolean setConfig(String tenantId, String configKey, String configValue, String configType, String description) {
        if (!StringUtils.hasText(tenantId) || !StringUtils.hasText(configKey)) {
            return false;
        }

        TenantConfig existingConfig = baseMapper.selectByTenantIdAndKey(tenantId, configKey);
        
        if (existingConfig != null) {
            // 更新现有配置
            existingConfig.setConfigValue(configValue);
            existingConfig.setConfigType(configType);
            existingConfig.setDescription(description);
            return updateById(existingConfig);
        } else {
            // 创建新配置
            TenantConfig newConfig = new TenantConfig();
            newConfig.setTenantId(tenantId);
            newConfig.setConfigKey(configKey);
            newConfig.setConfigValue(configValue);
            newConfig.setConfigType(configType);
            newConfig.setDescription(description);
            newConfig.setIsSystem(0); // 默认为用户配置
            return save(newConfig);
        }
    }

    @Override
    public boolean setConfig(String tenantId, String configKey, Object configValue) {
        if (configValue == null) {
            return deleteConfig(tenantId, configKey);
        }

        String valueStr;
        String configType;

        if (configValue instanceof String) {
            valueStr = (String) configValue;
            configType = TenantConfig.ConfigType.STRING.getCode();
        } else if (configValue instanceof Number) {
            valueStr = configValue.toString();
            configType = TenantConfig.ConfigType.NUMBER.getCode();
        } else if (configValue instanceof Boolean) {
            valueStr = configValue.toString();
            configType = TenantConfig.ConfigType.BOOLEAN.getCode();
        } else {
            try {
                valueStr = objectMapper.writeValueAsString(configValue);
                configType = TenantConfig.ConfigType.JSON.getCode();
            } catch (Exception e) {
                log.error("配置值序列化失败: {}", configValue, e);
                return false;
            }
        }

        return setConfig(tenantId, configKey, valueStr, configType, null);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @DataCacheEvict(prefix = "tenant:config", key = "#tenantId + ':' + #configKey")
    public boolean deleteConfig(String tenantId, String configKey) {
        if (!StringUtils.hasText(tenantId) || !StringUtils.hasText(configKey)) {
            return false;
        }

        LambdaQueryWrapper<TenantConfig> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(TenantConfig::getTenantId, tenantId)
               .eq(TenantConfig::getConfigKey, configKey);
        
        return remove(wrapper);
    }

    @Override
    @DataCache(prefix = "tenant:configs", key = "#tenantId", expireTime = 1800)
    public List<TenantConfig> getTenantConfigs(String tenantId) {
        if (!StringUtils.hasText(tenantId)) {
            return List.of();
        }
        return baseMapper.selectByTenantId(tenantId);
    }

    @Override
    public Map<String, String> getTenantConfigMap(String tenantId) {
        List<TenantConfig> configs = getTenantConfigs(tenantId);
        return configs.stream()
                .collect(Collectors.toMap(
                    TenantConfig::getConfigKey,
                    TenantConfig::getConfigValue,
                    (existing, replacement) -> replacement
                ));
    }

    @Override
    public List<TenantConfig> getSystemConfigs(String tenantId) {
        if (!StringUtils.hasText(tenantId)) {
            return List.of();
        }
        return baseMapper.selectSystemConfigs(tenantId);
    }

    @Override
    public List<TenantConfig> getUserConfigs(String tenantId) {
        if (!StringUtils.hasText(tenantId)) {
            return List.of();
        }
        return baseMapper.selectUserConfigs(tenantId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean batchSetConfigs(String tenantId, Map<String, Object> configs) {
        if (!StringUtils.hasText(tenantId) || configs == null || configs.isEmpty()) {
            return false;
        }

        try {
            for (Map.Entry<String, Object> entry : configs.entrySet()) {
                setConfig(tenantId, entry.getKey(), entry.getValue());
            }
            return true;
        } catch (Exception e) {
            log.error("批量设置租户配置失败: {}", tenantId, e);
            return false;
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean initDefaultConfigs(String tenantId) {
        if (!StringUtils.hasText(tenantId)) {
            return false;
        }

        try {
            Map<String, Object> defaultConfigs = getDefaultConfigs();
            return batchSetConfigs(tenantId, defaultConfigs);
        } catch (Exception e) {
            log.error("初始化租户默认配置失败: {}", tenantId, e);
            return false;
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean copyConfigs(String sourceTenantId, String targetTenantId) {
        if (!StringUtils.hasText(sourceTenantId) || !StringUtils.hasText(targetTenantId)) {
            return false;
        }

        try {
            List<TenantConfig> sourceConfigs = getTenantConfigs(sourceTenantId);
            for (TenantConfig config : sourceConfigs) {
                // 跳过系统配置
                if (config.getIsSystem() == 1) {
                    continue;
                }
                
                setConfig(targetTenantId, config.getConfigKey(), config.getConfigValue(), 
                         config.getConfigType(), config.getDescription());
            }
            return true;
        } catch (Exception e) {
            log.error("复制租户配置失败: {} -> {}", sourceTenantId, targetTenantId, e);
            return false;
        }
    }

    @Override
    public boolean existsConfig(String tenantId, String configKey) {
        return getConfigValue(tenantId, configKey) != null;
    }

    /**
     * 获取默认配置
     */
    private Map<String, Object> getDefaultConfigs() {
        Map<String, Object> configs = new HashMap<>();
        
        // 系统配置
        configs.put("system.theme", "default");
        configs.put("system.language", "zh-CN");
        configs.put("system.timezone", "Asia/Shanghai");
        
        // 功能配置
        configs.put("feature.file_upload", true);
        configs.put("feature.online_chat", true);
        configs.put("feature.video_call", false);
        
        // 限制配置
        configs.put("limit.max_file_size", 100 * 1024 * 1024); // 100MB
        configs.put("limit.max_storage_per_user", 1024 * 1024 * 1024); // 1GB
        configs.put("limit.max_concurrent_sessions", 5);
        
        // 安全配置
        configs.put("security.password_min_length", 6);
        configs.put("security.password_require_special_char", false);
        configs.put("security.session_timeout", 30 * 60); // 30分钟
        configs.put("security.max_login_attempts", 5);
        
        // 通知配置
        configs.put("notification.email_enabled", true);
        configs.put("notification.sms_enabled", false);
        configs.put("notification.push_enabled", true);
        
        return configs;
    }
}
